﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ClusterAggregation.Datum
{
    /**
     * Grey pixel distance function.
     */
    public class CGreyscaledPixelDistanceFunction : ISimilarity
    {
        /** contrast adapter to weigh down on the grayscale values */
        public const double contracstAdapter = 0.17;
        public int          SMALL_DISTANCE = 12;


        public double[,] getMatrix(AData[] arg)
        {
            double[,] calc = new double[arg.Length, arg.Length];

            CPixel[] tmp = (CPixel[])arg; // casting

            //first iteration
            for (int i = 0; i < arg.Length; i++)
            {

                for (int j = i; j < arg.Length; j++)
                {
                    calc[i, j] = similarity(tmp[i], tmp[j]);
                }
            }
            return calc;
        }

        public double[,] getFullMatrix(AData[] arg)
        {
            int arLength = arg.Length;
        //    Thread.Sleep(4);
            double[,] calc = new double[arLength, arLength];

            //CPixel[] tmp = (CPixel[])arg; // casting

            for (int i = 0; i < arg.Length; i++)
            {
                for (int j = 0; j < arg.Length; j++)
                {
                    calc[i, j] = similarity(arg[i], arg[j]);
                }
            }
            return calc;
        }

        public double similarity(AData a, AData b)
        {
            double sum = 0;
            int i = 0;
            for (; i < a.coordinates.Length -1; i++)
                sum += (a.coordinates[i] - b.coordinates[i]) * (a.coordinates[i] - b.coordinates[i]);

            // last pixel is greyscaled, give special weight
            if (sum < SMALL_DISTANCE)
                sum += ( contracstAdapter / 255) *Math.Sqrt( (a.coordinates[i] - b.coordinates[i]) * (a.coordinates[i] - b.coordinates[i]) ) / 255;
            else 
            // ther are not very close, so color cannot add more than a few percentages to total distance;
                sum += /*(sum / a.coordinates.Length) * (contracstAdapter / 255)
                    */ (a.coordinates[i] - b.coordinates[i]) * (a.coordinates[i] - b.coordinates[i]);
            return Math.Sqrt(Math.Sqrt(sum));
        }
    }
}
